const express = require('express')
const router = express.Router()
const WebSocket = require('ws');
const sleep = require('../../util/sleep');
const wss = new WebSocket.Server({ port: 3001 }, () => {
    console.log("ws启动成功！");
});

// 协议
// {"type":"command","cmd":"","data":"3213222","msg":"xxx"}
// {"type":"heart"}

const cCmd = {
    type: "command",
    cmd: "",
    data: "",
    msg: ""
}

const cHeart = {
    type: "heart"
}

const cRes = {
    code: 0,
    data: '',
    msg: ''
};
const norm = 'norm';
const lite = 'lite';
let sockets = {}; // 连接池
let recvHandle = {};

// 连接池有新连接
wss.on('connection', function connection(ws, req) {
    console.log('ws url: ' + req.url);
    let id = req.url.slice(1); // 截几位字符串根据自己实际获得的url来看
    if (sockets.hasOwnProperty(id)) {
        sockets[id].terminate();
        console.log('ws id: ' + id + ', 已存在删除上一个连接');
    }

    ws.id = id;
    sockets[id] = ws;
    console.log('ws连接池加入新连接: ' + id);

    //发生错误
    ws.on('error', function error(error) {
        delete sockets[id];
        console.log('ws id: ' + this.id + ', error:' + error);
    });

    //断开连接
    ws.on('close', function close(close) {
        delete sockets[id];
        console.log('ws id: ' + this.id + ', 已关闭');
    });

    //收到消息
    ws.on('message', function message(message) {
        let cmd = JSON.parse(message);
        // if (cmd.type == 'command') {
        //     if (cmd.cmd == 'message' ||
        //         cmd.cmd == 'login' ||
        //         cmd.cmd == 'sendCode' ||
        //         cmd.cmd == 'smsLogin' ||
        //         cmd.cmd == 'smsReg' ||
        //         cmd.cmd == 'smsUpdatePassword' ||
        //         cmd.cmd == 'exit') {
        //         if (recvHandle[cmd.cmd] != null) {
        //             console.log('ws id: ' + this.id + ', received = %s', message);
        //             recvHandle[cmd.cmd](cmd.data);
        //         }
        //     }
        // }
    });
});

const interval = setInterval(function () {
    wss.clients.forEach(function each(ws) {
        if (ws.id && sockets.hasOwnProperty(ws.id)) {
            // 发送心跳
            ws.send(JSON.stringify(cHeart));
        } else {
            console.log('ws id: ' + ws.id + ', 已移除不能发送心跳');
        }
    });
}, 5 * 1000);

// 服务端socket关闭
wss.on('close', function close() {
    console.log('ws连接池关闭');
    sockets = {};
    clearInterval(interval);
});

function recvApiRes(cmd, req, res) {
    var result = { ...cRes };
    if (req.body) {
        if (recvHandle[cmd] != null) {
            console.log('api recv ' + cmd + ', result = ' + JSON.stringify(req.body))
            recvHandle[cmd](req.body.data);
        } else {
            console.log('api recv ' + cmd + ', but handle is null !');
        }
    } else {
        result.code = 1;
        result.message = "解析请求异常";
    }
    return res.json(result);
}
router.post('/message', async function (req, res) {
    recvApiRes('message', req, res);
})
router.post('/login', async function (req, res) {
    recvApiRes('login', req, res);
})
router.post('/loginVerify', async function (req, res) {
    recvApiRes('loginVerify', req, res);
})
router.post('/sendCode', async function (req, res) {
    recvApiRes('sendCode', req, res);
})
router.post('/smsLogin', async function (req, res) {
    recvApiRes('smsLogin', req, res);
})
router.post('/smsReg', async function (req, res) {
    recvApiRes('smsReg', req, res);
})
router.post('/smsUpdatePassword', async function (req, res) {
    recvApiRes('smsUpdatePassword', req, res);
})
router.post('/exit', async function (req, res) {
    recvApiRes('exit', req, res);
})

function message(phone, password, device, phoneInfo, pList) {
    let pro = new Promise(async (resolve, reject) => {
        let arr = await waitWebSocket(norm);
        if (arr.length == 0) {
            resolve({ code: 1, data: '', msg: '没有可用的连接，message发送失败' })
            return;
        } else {
            let ws = arr[0];
            let cmd = { ...cCmd };
            cmd.cmd = 'message';
            cmd.data = { phone: phone, password: password, device: device, phoneInfo: phoneInfo, pList: pList };
            ws.send(JSON.stringify(cmd));
        }

        recvHandle.message = function (data) {
            let res = { ...cRes };
            res.code = data.code;
            res.data = data.data;
            res.msg = data.msg;
            resolve(res);
            recvHandle.message = null;
        };
    });

    return exec(pro);
}

function login(phone, password, device, phoneInfo) {
    let pro = new Promise(async (resolve, reject) => {
        let arr = await waitWebSocket(lite);
        if (arr.length == 0) {
            resolve({ code: 1, data: '', msg: '没有可用的连接，login发送失败' })
            return;
        } else {
            let ws = arr[0];
            let cmd = { ...cCmd };
            cmd.cmd = 'login';
            cmd.data = { phone: phone, password: password, device: device, phoneInfo: phoneInfo };
            ws.send(JSON.stringify(cmd));
        }

        recvHandle.login = function (data) {
            let res = { ...cRes };
            res.code = data.code;
            res.data = data.data;
            res.msg = data.msg;
            resolve(res);
            recvHandle.login = null;
        };
    });

    return exec(pro);
}

function loginVerify(code) {
    let pro = new Promise(async (resolve, reject) => {
        let arr = await waitWebSocket(lite);
        if (arr.length == 0) {
            resolve({ code: 1, data: '', msg: '没有可用的连接，loginVerify发送失败' })
            return;
        } else {
            let ws = arr[0];
            let cmd = { ...cCmd };
            cmd.cmd = 'loginVerify';
            cmd.data = { code: code };
            ws.send(JSON.stringify(cmd));
        }

        recvHandle.loginVerify = function (data) {
            let res = { ...cRes };
            res.code = data.code;
            res.data = data.data;
            res.msg = data.msg;
            resolve(res);
            recvHandle.loginVerify = null;
        };
    });

    return exec(pro);
}

function sendCode(phone, phoneInfo, device) {
    let pro = new Promise(async (resolve, reject) => {
        let arr = await waitWebSocket(lite);
        if (arr.length == 0) {
            resolve({ code: 1, data: '', msg: '没有可用的连接，sendCode发送失败' })
            return;
        } else {
            let ws = arr[0];
            let cmd = { ...cCmd };
            cmd.cmd = 'sendCode';
            cmd.data = { phone: phone, phoneInfo: phoneInfo, device:device};
            ws.send(JSON.stringify(cmd));
        }

        recvHandle.sendCode = function (data) {
            let res = { ...cRes };
            res.code = data.code;
            res.data = data.data;
            res.msg = data.msg;
            resolve(res);
            recvHandle.sendCode = null;
        };
    });

    return exec(pro);
}

function smsLogin(code) {
    let pro = new Promise(async (resolve, reject) => {
        let arr = await waitWebSocket(lite);
        if (arr.length == 0) {
            resolve({ code: 1, data: '', msg: '没有可用的连接，smsLogin发送失败' })
            return;
        } else {
            let ws = arr[0];
            let cmd = { ...cCmd };
            cmd.cmd = 'smsLogin';
            cmd.data = { code: code };
            ws.send(JSON.stringify(cmd));
        }

        recvHandle.smsLogin = function (data) {
            let res = { ...cRes };
            res.code = data.code;
            res.data = data.data;
            res.msg = data.msg;
            resolve(res);
            recvHandle.smsLogin = null;
        };
    });

    return exec(pro);
}

function smsReg(code, password) {
    let pro = new Promise(async (resolve, reject) => {
        let arr = await waitWebSocket(lite);
        if (arr.length == 0) {
            resolve({ code: 1, data: '', msg: '没有可用的连接，smsReg发送失败' })
            return;
        } else {
            let ws = arr[0];
            let cmd = { ...cCmd };
            cmd.cmd = 'smsReg';
            cmd.data = { code: code, password: password };
            ws.send(JSON.stringify(cmd));
        }

        recvHandle.smsReg = function (data) {
            let res = { ...cRes };
            res.code = data.code;
            res.data = data.data;
            res.msg = data.msg;
            resolve(res);
            recvHandle.smsReg = null;
        };
    });

    return exec(pro);
}

function smsUpdatePassword(code) {
    let pro = new Promise(async (resolve, reject) => {
        let arr = await waitWebSocket(lite);
        if (arr.length == 0) {
            resolve({ code: 1, data: '', msg: '没有可用的连接，smsUpdatePassword发送失败' })
            return;
        } else {
            let ws = arr[0];
            let cmd = { ...cCmd };
            cmd.cmd = 'smsUpdatePassword';
            cmd.data = { code: code };
            ws.send(JSON.stringify(cmd));
        }

        recvHandle.smsUpdatePassword = function (data) {
            let res = { ...cRes };
            res.code = data.code;
            res.data = data.data;
            res.msg = data.msg;
            resolve(res);
            recvHandle.smsUpdatePassword = null;
        };
    });

    return exec(pro);
}

function exit() {
    let pro = new Promise(async (resolve, reject) => {
        let arr = await waitWebSocket(lite);
        if (arr.length == 0) {
            resolve({ code: 1, data: '', msg: '没有可用的连接，exit发送失败' })
            return;
        } else {
            let ws = arr[0];
            let cmd = { ...cCmd };
            cmd.cmd = 'exit';
            cmd.data = "";
            ws.send(JSON.stringify(cmd));
        }

        recvHandle.exit = function (data) {
            let res = { ...cRes };
            res.code = data.code;
            res.data = data.data;
            res.msg = data.msg;
            resolve(res);
            recvHandle.exit = null;
        };
    });

    return exec(pro);
}

async function waitLite() {
    let arr = await waitWebSocket(lite);
    if (arr.length == 0) {
        return { code: 1, data: '', msg: '没有可用的连接，exit发送失败' }
    } 

    return { ...cRes };
}

async function waitWebSocket(id) {
    for (let index = 0; index < 5; index++) {
        let arr = [];
        for(let index in sockets) {
            if(id == index) {
                arr.push(sockets[index]);
            }
        }
        if (arr.length == 0) {
            console.log('ws ' + id + ' 没有可用的连接，等待连接中');
            await sleep(4000);
        } else {
            return arr;
        }
    }
    return [];
}

function exec(wsPromise, timeout = 60 * 1000) {
    let timeoutPromise = new Promise((resolve, reject) => {
        setTimeout(() => {
            let res = { ...cRes };
            res.code = 1;
            res.msg = '请求超时'
            resolve(res)
        }, timeout)
    })

    let totalPromise = Promise.race([wsPromise, timeoutPromise])
        .then(data => {
            console.log('ws ok: ' + JSON.stringify(data))
            return data
        })
        .catch(err => {
            console.log('ws err: ' + JSON.stringify(err))
            throw err
        })

    return totalPromise;
}

module.exports = {
    message,
    login,
    loginVerify,
    sendCode,
    smsLogin,
    smsReg,
    smsUpdatePassword,
    exit,
    waitLite,
    router
}
